/**
 *
 * © Bahadir Zeren 2011
 * bzeren@gmail.com
 * No warranties, express or implied, are made for this program.
 *
 */
package org.baatar.opt.genetic.set.covering.binary;

import java.util.BitSet;
import org.baatar.opt.genetic.chromosome.IChromosome;
import org.baatar.opt.genetic.crossover.ICrossoverOperator;
import org.baatar.util.RandomUtil;

/**
 * 
 * 
 * @author B_ZEREN
 */
public final class SCCrossover implements ICrossoverOperator<Boolean, BitSet> {

    @Override
    public int crossover(IChromosome<Boolean, BitSet> population[],
                            int startingChildIndex,
                            IChromosome<Boolean, BitSet> mother,
                            IChromosome<Boolean, BitSet> father,
                            double worstFitness,
                            RandomUtil random) throws CloneNotSupportedException {
        int res = startingChildIndex;

        double pMot = (Math.abs(worstFitness - mother.getFitness()) / 
                        Math.abs(2.0 * worstFitness - mother.getFitness() - father.getFitness()));

        IChromosome<Boolean, BitSet> ch1 = (IChromosome<Boolean, BitSet>) mother.clone();
        IChromosome<Boolean, BitSet> ch2 = (IChromosome<Boolean, BitSet>) father.clone();

        int chromosomeLength = mother.getChromosomeLength();
        boolean motherBool = false;
        boolean fatherBool = false;
        double r = 0.0;

        for (int i = 0; i < chromosomeLength; i++) {
            motherBool = mother.getGeneValue(i);
            fatherBool = father.getGeneValue(i);
            if (motherBool ^ fatherBool) {
                r = random.getRandDouble();
                if (r > pMot) {
                    if (fatherBool) {
                        ch1.setGeneValue(i, true);
                        ch2.setGeneValue(i, false);
                    } else {
                        ch1.setGeneValue(i, false);
                        ch2.setGeneValue(i, true);
                    }
                }
            }
        }

        population[res] = ch1;
        res++;
        population[res] = ch2;
        res++;
        return res;
    }
    
    /**
     * Clones the this object.
     * 
     * @return Object new cloned object.
     * 
     * @throws CloneNotSupportedException is trown if this object doesnt
     * implements Cloneable interface.
     */
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
